# -*- python -*-
# vim: syntax=python
import sys,os

master_repo = 'git://github.com/spring/spring.git'
mingwlibs_repo = 'git://github.com/spring/mingwlibs.git'

c = BuildmasterConfig = {}
c['slaves'] = []
c['builders'] = []
c['schedulers'] = []
c['status'] = []

# http://docs.buildbot.net/latest/manual/cfg-global.html#data-lifetimea
# automaticly delete old logs
c['changeHorizon'] = 200
c['buildHorizon'] = 100
c['eventHorizon'] = 50
c['logHorizon'] = 40

# import the passwords from another file. this way we can keep config in git
import passwords
reload(passwords)
c['db_url'] = "mysql://buildbot:%s@localhost/buildbot?max_idle=300" % passwords.db

####### build properties

c['properties'] = {
	'default-branch': 'develop',
	'default-config': 'default',
}

def determine(props, key, defKey, defVal):
	if props.hasProperty(key) and props[key]:
		return props[key]
	elif props.hasProperty(defKey):
		return props[defKey]
	return defVal

def determine_branch(props):
	return determine(props, 'branch', 'default-branch', 'develop')

def determine_config(props):
	return determine(props, 'config', 'default-config', 'default')

def WithProps(fmt):
	fmt = fmt.replace('%(bc)s', '%(branch)s / %(config)s')
	return WithProperties(fmt, branch=determine_branch, config=determine_config)

def WithConfig(fmt = '%s'):
	return WithProps(fmt.replace('%s', '%(config)s'))

def WithBranch(fmt = '%s'):
	return WithProps(fmt.replace('%s', '%(branch)s'))

####### build configs

build_configs = {
	'validation': ['-DDEBUG_SIGNAL_NANS=TRUE', '-DCMAKE_BUILD_TYPE=DEBUG'],
	'debug'     : ['-DCMAKE_BUILD_TYPE=DEBUG'],
	'default'   : ['-DCMAKE_BUILD_TYPE=RELWITHDEBINFO'],
	'fast'      : ['-DCMAKE_BUILD_TYPE=RELEASE'],
	'profiling' : ['-DCMAKE_BUILD_TYPE=PROFILE'],
	'syncdebug' : ['-DCMAKE_BUILD_TYPE=DEBUG', '-DSYNCDEBUG=TRUE', '-DDEBUG_SIGNAL_NANS=FALSE'],
	'tracesync' : ['-DCMAKE_BUILD_TYPE=RELWITHDEBINFO', '-DTRACE_SYNC=TRUE'],
}

####### BUILDSLAVES

from buildbot.buildslave import BuildSlave


# the `jobs' property is the -j argument to make on this slave
c['slaves'].append(BuildSlave("abma1",          passwords.abma1,      max_builds=1, properties={'jobs': 1}))
c['slaves'].append(BuildSlave("abma2",          passwords.abma2,      max_builds=1, properties={'jobs': 1}))
#c['slaves'].append(BuildSlave("koshi1",         passwords.koshi1,     max_builds=1, properties={'jobs': 2}))
c['slaves'].append(BuildSlave("zydox1",         passwords.zydox1,     max_builds=1, properties={'jobs': 2}))
c['slaves'].append(BuildSlave("jk1",            passwords.jk1,        max_builds=1, properties={'jobs': 4}))
c['slaves'].append(BuildSlave("supermario",     passwords.supermario, max_builds=1, properties={'jobs': 4}))
c['slaves'].append(BuildSlave("turboss",        passwords.turboss,    max_builds=1, properties={'jobs': 8}))
c['slaves'].append(BuildSlave("turboss1",       passwords.turboss1,   max_builds=1, properties={'jobs': 4}))
c['slaves'].append(BuildSlave("validation",     passwords.validation, max_builds=1, properties={'jobs': 2}))
c['slaves'].append(BuildSlave("buildslave-i686",passwords.buildslave_i686, max_builds=1, properties={'jobs': 1}))
c['slaves'].append(BuildSlave("buildslave-x64", passwords.buildslave_x64,  max_builds=1, properties={'jobs': 1}))
c['slaves'].append(BuildSlave("buildslave-win32", passwords.buildslave_win32,  max_builds=1, properties={'jobs': 1}))

c['slavePortnum'] = 9989
#win_linux_slaves = ["koshi1"]

####### SCHEDULERS

def changeIsImportant(change):
	for name in change.files:
		if (name.endswith('.cpp') or name.endswith('.c') or
		    name.endswith('.hpp') or name.endswith('.h') or
		    name.endswith('.inl') or name.endswith('CMakeLists.txt')):
			return True
	return False

import string
def workdir_per_branch(sourcestamps):
	valid_chars = "-_.()%s%s" % (string.ascii_letters, string.digits)
	filename = sourcestamps[0].branch
	return ''.join(c for c in filename if c in valid_chars)

from buildbot.changes.filter import ChangeFilter
from buildbot.schedulers import basic, timed, forcesched
from buildbot.schedulers.forcesched import StringParameter

c['schedulers'].append(basic.AnyBranchScheduler(
	name="full-sched",
	treeStableTimer=60,
	fileIsImportant=changeIsImportant,
	change_filter=ChangeFilter(branch_re='develop|release|post_release'),
	builderNames=["full-windows-test", "full-windows-x64", "msvc", "quick-macosx", "validationtests", "linux-static-x64"]))

c['schedulers'].append(basic.AnyBranchScheduler(
	name="release-sched",
	treeStableTimer=60,
	change_filter=ChangeFilter(branch_re='master'),
	builderNames=["full-windows-test", "full-windows-x64", "msvc", "full-macosx", "linux-static-x32", "linux-static-x64", "sourcebuilder", "wikibuilder", "doxygen"]))

c['schedulers'].append(timed.Nightly(
	name='nightly',
	branch='develop',
	fileIsImportant=changeIsImportant,
	onlyIfChanged=True,
	builderNames=["cppcheck", "full-macosx", "linux-static-x32"], hour=6, minute=0))

c['schedulers'].append(forcesched.ForceScheduler(
			name="force",
			builderNames=[
					"mingwlibs",
					"msvc",
					"full-windows-test",
					"full-windows-x64",
					"full-macosx",
					"linux-static-x32",
					"linux-static-x64",
					"sourcebuilder",
					"wikibuilder",
					"cppcheck",
					"doxygen",
					"validationtests",
					"quick-macosx",
				],
			branch=forcesched.StringParameter(name="branch", label="branch:", required=True, size=30, default="develop")
		)
	)


# prioritize release builds
def nextBuild(bldr, requests):
    for r in requests:
        if r.source.branch == 'master':
            return r
    return requests[0]

####### BUILDERS

from buildbot.process.factory import BuildFactory
from buildbot.steps.source import Git
from buildbot.steps.shell import Compile, Test, ShellCommand, WarningCountingShellCommand, WithProperties
from buildbot.status.builder import WARNINGS, FAILURE, SUCCESS

# common build config steps ---------------------------------------------@

# description / descritionDone style : doing X / done X

class LocalPreScript(ShellCommand):
	name = 'local pre script'
	description = "executing local pre script"
	descriptionDone = "executed local pre script"
	command = ['buildbot/slave/safe-exec.sh', '../../local.start', WithBranch()]
	haltOnFailure = False
#	hideStepIf = lambda s, result: result==SUCCESS
	alwaysRun = True

class LocalPostScript(ShellCommand):
	name = 'local post script'
	description = "executing local post script"
	descriptionDone = "executed local post script"
	command = ['buildbot/slave/safe-exec.sh', '../../local.stop', WithBranch()]
	haltOnFailure = False
#	hideStepIf = lambda s, result: result==SUCCESS
	alwaysRun = True

class GitRenameLocalBranch1(ShellCommand):
	name = 'gitRenameLocalBranch1'
	description = [WithBranch('renaming local git branch to temp')]
	descriptionDone = [WithBranch('renamed local git branch to temp')]
	command = ['git', 'branch', '-M', 'temp']
	haltOnFailure = True

class GitRenameLocalBranch2(ShellCommand):
	name = 'gitRenameLocalBranch2'
	description = [WithBranch('renaming local git branch to %s')]
	descriptionDone = [WithBranch('renamed local git branch to %s')]
	command = ['git', 'branch', '-M', WithBranch()]
	haltOnFailure = True

class BuildConfigNinja(Compile):
	warnOnWarnings  = True
	description = [WithProps('building %(bc)s config')]
	descriptionDone = [WithProps('built %(bc)s config')]
	name = 'buildConfigNinja'
	command = ['ninja', '-k 10', WithProps('-j%(jobs:-1)s'), '-C', WithConfig('build/%s')]

class BuildConfigNinjaWiki(BuildConfigNinja):
	name = 'buildConfigNinja'
	command = ['ninja', 'engine-headless', 'manpages', '-k 10', WithProps('-j%(jobs:-1)s'), '-C', WithConfig('build/%s')]

class TestConfig(Test):
	command = ['buildbot/slave/run-tests.sh',WithConfig(), WithBranch()]

class CreateBuildDirPy(ShellCommand) :
	name = "build dir create"
	haltOnFailure = True
	description = [WithProps('creating %(bc)s dir')]
	descriptionDone = [WithProps('created %(bc)s dir')]
	command = ["python2", "buildbot/slave/create-build-dirs.py", WithConfig(), WithBranch()]

	def __init__(self, extra_opts = None, **kwargs):
		if extra_opts is None:
			extra_opts = []
		self.extra_opts = extra_opts
		ShellCommand.__init__(self, **kwargs)

		#mandatory for later (automatic) re-creation of step object
		self.addFactoryArguments(extra_opts = extra_opts)

	def start(self):
		#substitute the correct (cmake) arguments for the configuration
		config = determine_config(self.getProperties())
		self.command += build_configs[config] + self.extra_opts
		ShellCommand.start(self)

class CreateInstaller(ShellCommand) :
	name = "create installer"
	description = [WithProps('creating %(bc)s installer')]
	descriptionDone = [WithProps('created %(bc)s installer')]
	# last argument is max number of threads (e.g., for 7z)
	command = ['./buildbot/slave/win/make_installer.sh', WithConfig(), WithBranch(), WithProps('%(jobs:-on)s')]

class CreateMacBundle(ShellCommand) :
	name = "create Mac .app bundle"
	description = [WithProps('creating %(bc)s Mac bundle')]
	descriptionDone = [WithProps('created %(bc)s Mac bundle')]
	command = ['./buildbot/slave/osx/create_Mac_bundle.sh', WithConfig(), WithBranch()]

class CreateLinuxStaticBundle(ShellCommand) :
	name = "create linux bundle"
	description = [WithProps('creating %(bc)s bundle')]
	descriptionDone = [WithProps('created %(bc)s bundle')]
	command = ['./buildbot/slave/linux/create_linux_static_bundle.sh', WithConfig(), WithBranch()]

class CreateSourceBundle(ShellCommand) :
	name = "create source bundle"
	description = [WithProps('creating %(bc)s bundle')]
	descriptionDone = [WithProps('created %(bc)s bundle')]
	command = ['./buildbot/slave/source/make_source_package.sh', WithConfig(), WithBranch()]

class HashStuff(ShellCommand):
	name = "md5sums"
	description = [WithProps('hashing %(bc)s')]
	descriptionDone = [WithProps('hasheded %(bc)s')]
	command = ['./buildbot/slave/create-md5sums.py', WithConfig(), WithBranch(), ".7z", ".exe", ".zip", ".tar.gz", ".tar.lzma"]

class RsyncStuff(ShellCommand) :
	name = "rsync"
	description = [WithProps('uploading %(bc)s')]
	descriptionDone = [WithProps('uploaded %(bc)s')]
	command = ['./buildbot/slave/rsync.sh', WithConfig(), WithBranch()]

class RsyncMac(ShellCommand) :
	name = "rsync"
	description = [WithProps('uploading %(bc)s')]
	descriptionDone = [WithProps('uploaded %(bc)s')]
	command = ['./buildbot/slave/osx/rsync-mac.sh', WithConfig(), WithBranch()]

class SyncSubmodules(ShellCommand) :
	name = "syncsubmodules"
	description = 'syncing .gitmodules with .git/config'
	descriptionDone = 'synced submodule paths'
	command = ['git', 'submodule', 'sync']

class InitSubmodules(ShellCommand) :
	name = "submodules"
	description = 'updating submodules'
	descriptionDone = 'updated submodules'
	command = ['git', 'submodule', 'update', '--init']

class CppCheck(WarningCountingShellCommand) :
	name = "cppcheck"
	description = "running cppcheck"
	descriptionDone = "ran cppcheck"
	warnOnWarnings = True
	warningPattern = '\[[^:]+\:[0-9]+\].*'
	command = ['./buildbot/slave/cppcheck/cppcheck.sh', WithProps('-j%(jobs:-1)s')]

	def __init__(self, **kwargs):
		# cppcheck --quiet may be quiet for a long while...
		kwargs.update({'timeout': 10800})
		WarningCountingShellCommand.__init__(self, **kwargs)

class GenerateSources(WarningCountingShellCommand) :
	name = "generatesources"
	description = "creating source files"
	descriptionDone = "created source files"
	warnOnWarnings = True
	command = ['ninja', 'generateSources', WithProps('-j%(jobs:-1)s'), '-C', WithConfig('build/%s')]

class BuildDocs(WarningCountingShellCommand) :
	name = "doxygen"
	description = "creating docs"
	descriptionDone = "created docs"
	warnOnWarnings = True
	command = ['buildbot/slave/create-doc.sh', WithConfig(), WithBranch()]

class ValidationTestPrepare(WarningCountingShellCommand) :
	name = "validation test prepare"
	description = "preparing validation tests"
	descriptionDone = "prepared validation tests"
	warnOnWarnings = True
	haltOnFailure = True
	command = ['./buildbot/slave/validation/tests-prepare.sh', WithConfig(), WithBranch()]
	def __init__(self, game, map, ai, version, **kwargs):
		self.game = game
		self.map = map
		self.ai = ai
		self.version = version
		WarningCountingShellCommand.__init__(self, **kwargs)
		self.addFactoryArguments(game = game)
		self.addFactoryArguments(map = map)
		self.addFactoryArguments(ai = ai)
		self.addFactoryArguments(version = version)
	def start(self):
		self.command.append(self.game)
		self.command.append(self.map)
		self.command.append(self.ai)
		self.command.append(self.version)
		WarningCountingShellCommand.start(self)

class ValidationTestRun(WarningCountingShellCommand) :
	name = "validation test"
	warnOnWarnings = True
	command = ['./buildbot/slave/validation/tests-run.sh', WithConfig(), WithBranch()]
	warningPattern = "(.*Error:|^#\d+ ).*"
	def __init__(self, game, map, ai, version, **kwargs):
		self.game = game
		self.map = map
		self.ai = ai
		self.version = version
		WarningCountingShellCommand.__init__(self, **kwargs)
		self.addFactoryArguments(game = game)
		self.addFactoryArguments(map = map)
		self.addFactoryArguments(ai = ai)
		self.addFactoryArguments(version = version)

		self.addSuppression([(None,".*LuaRules::RunCallIn: error = 2, RecvFromSynced,.*", None, None)])
		self.description = ["testing %s with %s" % (self.ai, self.game)]
		self.descriptionDone = ["tested %s with %s" % (self.ai, self.game)]

	def start(self):
		self.command.append(self.game)
		self.command.append(self.map)
		self.command.append(self.ai)
		self.command.append(self.version)
		WarningCountingShellCommand.start(self)

	def evaluateCommand(self, cmd):
		if cmd.rc != 0:
			return FAILURE
		if self.warnCount >= 1:
			return WARNINGS
		return SUCCESS

class ValidationTestInstall(WarningCountingShellCommand) :
	name = "validation test install"
	description = "install"
	descriptionDone = "installed"
	warnOnWarnings = True
	command = ['./buildbot/slave/validation/tests-install.sh', WithConfig(), WithBranch()]

class ValidationTestCleanup(WarningCountingShellCommand) :
	name = "validation test cleanup"
	description = "cleaning validation tests"
	descriptionDone = "cleaned validation tests"
	warnOnWarnings = True
	command = ['./buildbot/slave/validation/tests-cleanup.sh', WithConfig(), WithBranch()]

class ValidationTestAnalyze(WarningCountingShellCommand) :
	name = "analyze core dumps"
	warnOnWarnings = True
	command = ['./buildbot/slave/validation/tests-analyze.sh', WithConfig(), WithBranch()]
	alwaysRun = True
	def __init__(self, game, map, ai, version, **kwargs):
		self.game = game
		self.map = map
		self.ai = ai
		self.version = version
		WarningCountingShellCommand.__init__(self, **kwargs)
		self.addFactoryArguments(game = game)
		self.addFactoryArguments(map = map)
		self.addFactoryArguments(ai = ai)
		self.addFactoryArguments(version = version)
		self.description = ["analyzing %s with %s" % (self.ai, self.game)]
		self.descriptionDone = ["analyzed %s with %s" % (self.ai, self.game)]
	def start(self):
		self.command.append(self.game)
		self.command.append(self.map)
		self.command.append(self.ai)
		self.command.append(self.version)
		ShellCommand.start(self)

class UpdateMingwLibs(WarningCountingShellCommand) :
	name = "update mingwlibs"
	description = "updating mingwlibs"
	descriptionDone = "updated mingwlibs"
	warnOnWarnings = True
	command = ['./buildbot/slave/win/update-mingwlibs.sh', WithConfig(), WithBranch()]

class UpdateMsvcLibs(WarningCountingShellCommand) :
	name = "update mingwlibs"
	description = "updating mingwlibs"
	descriptionDone = "updated mingwlibs"
	warnOnWarnings = True
	command = ['python', 'buildbot/slave/update-mingwlibs.py', WithConfig(), WithBranch()]

class TestIfStaticLinked(ShellCommand) :
	name = "static link test"
	warnOnWarnings = True
#	hideStepIf = lambda s, result: result==SUCCESS
	command = ['./buildbot/slave/linux/static-test-if-shared-linked.sh', WithConfig('build/%s/spring')]
	def __init__(self, libname = '', name = '', **kwargs):
		if not name:
			name = libname
		self.name = name
		self.libname = libname
		ShellCommand.__init__(self, **kwargs)
		self.description = ["testing %s" % (self.name)]
		self.descriptionDone = ["tested %s" % (self.name)]

		#mandatory for later (automatic) re-creation of step object
		self.addFactoryArguments(libname = libname, name = name)

	def start(self):
		self.command.append(self.libname)
		ShellCommand.start(self)

	def evaluateCommand(self, cmd):
		if cmd.rc == 0:
			return SUCCESS
		if cmd.rc == 1:
			return WARNINGS
		return FAILURE

class ShowSharedLinkedLibraries(ShellCommand) :
	name = "ldd"
	description = "running ldd"
	descriptionDone = "remaining libraries"
	warnOnWarnings = True
	command = ['./buildbot/slave/linux/static-show-used-dynamic-libraries.sh', WithConfig('build/%s/spring')]

class ShowSharedLinkedLibrariesUnitsync(ShellCommand) :
	name = "ldd"
	description = "running ldd on unitsync"
	descriptionDone = "remaining libraries"
	warnOnWarnings = True
	command = ['./buildbot/slave/linux/static-show-used-dynamic-libraries.sh', WithConfig('build/%s/libunitsync.so')]

class HTMLManpages(ShellCommand) :
	name = "upload HTML ManPages"
	description = 'upload html manpages'
	descriptionDone = 'upload html manpages'
	command = ['./buildbot/slave/wiki/update_manpages.sh', WithConfig(), WithBranch()]

class WikiChangelog(ShellCommand) :
	name = "update Changelog wiki page"
	description = 'updating changelog wiki'
	descriptionDone = 'updated changelog wiki'
	command = ['./buildbot/slave/wiki/update_changelog.sh', WithConfig(), WithBranch()]

class WikiSpringSettings(ShellCommand) :
	name = "update Springsettings.cfg wiki page"
	description = 'updating springsettings.cfg wiki'
	descriptionDone = 'updated springsettings.cfg wiki'
	command = ['./buildbot/slave/wiki/update_springsettings_page.sh', WithConfig(), WithBranch()]

class WikiWeaponDefs(ShellCommand) :
	name = "update WeaponDefs wiki page"
	description = 'updating WeaponDefs wiki'
	descriptionDone = 'updated WeaponDefs wiki'
	command = ['./buildbot/slave/wiki/update_weapondefs_page.sh', WithConfig(), WithBranch()]

class BuildMingwBoost(WarningCountingShellCommand) :
	name = "build boost"
	description = "building boost"
	descriptionDone = "build boost"
	warnOnWarnings = True
	command = ['./buildbot/mingwlibs_boost.sh', WithConfig(), WithBranch()]

# end common build config steps -----------------------------------------@


class WindowsFullBuildFactory(BuildFactory):
	def __init__(self):
		BuildFactory.__init__(self)
		self.workdir = workdir_per_branch
		self.useProgress = False
		self.addStep( Git(repourl=master_repo) )
		self.addStep( GitRenameLocalBranch1() )
		self.addStep( GitRenameLocalBranch2() )
		self.addStep( SyncSubmodules() )
		self.addStep( InitSubmodules() )
		self.addStep( UpdateMingwLibs() )
		self.addStep( CreateBuildDirPy() )
		self.addStep( BuildConfigNinja() )
		self.addStep( TestConfig() )
		self.addStep( CreateInstaller() )
		self.addStep( HashStuff() )
		self.addStep( RsyncStuff() )

class LinuxFullBuildFactory(BuildFactory):
	def __init__(self):
		BuildFactory.__init__(self)
		self.workdir = workdir_per_branch
		self.useProgress = False
		self.addStep( Git(repourl=master_repo) )
		self.addStep( GitRenameLocalBranch1() )
		self.addStep( GitRenameLocalBranch2() )
		self.addStep( SyncSubmodules() )
		self.addStep( InitSubmodules() )
		self.addStep( CreateBuildDirPy() )
		self.addStep( BuildConfigNinja() )
		self.addStep( TestConfig() )

class MacOSXFullBuildFactory(BuildFactory):
	def __init__(self):
		BuildFactory.__init__(self)
		self.workdir = workdir_per_branch
		self.useProgress = False
		self.addStep( Git(repourl=master_repo) )
		self.addStep( GitRenameLocalBranch1() )
		self.addStep( GitRenameLocalBranch2() )
		self.addStep( SyncSubmodules() )
		self.addStep( InitSubmodules() )
		self.addStep( CreateBuildDirPy() )
		self.addStep( BuildConfigNinja() )
		self.addStep( TestConfig() )
		self.addStep( CreateMacBundle() )
		self.addStep( HashStuff() )
		self.addStep( RsyncMac() )

class LinuxStaticBuildFactory(BuildFactory):
	def __init__(self):
		BuildFactory.__init__(self)
		self.workdir = workdir_per_branch
		self.useProgress = False
		self.addStep( Git(repourl=master_repo) )
		self.addStep( LocalPreScript() )
		self.addStep( GitRenameLocalBranch1() )
		self.addStep( GitRenameLocalBranch2() )
		self.addStep( SyncSubmodules() )
		self.addStep( InitSubmodules() )
		self.addStep( CreateBuildDirPy() )
		self.addStep( BuildConfigNinja() )
		self.addStep( TestConfig() )
		self.addStep( TestIfStaticLinked(libname="boost") )
		self.addStep( TestIfStaticLinked(libname="minizip") )
		self.addStep( TestIfStaticLinked(libname="libz.", name="zlib") )
		self.addStep( TestIfStaticLinked(libname="SDL") )
		self.addStep( TestIfStaticLinked(libname="glew") )
		self.addStep( TestIfStaticLinked(libname="libIL", name="devil") )
		self.addStep( TestIfStaticLinked(libname="jpeg") )
		self.addStep( TestIfStaticLinked(libname="png") )
		self.addStep( TestIfStaticLinked(libname="freetype") )
		self.addStep( TestIfStaticLinked(libname="vorbis") )
		self.addStep( TestIfStaticLinked(libname="ogg") )
		self.addStep( TestIfStaticLinked(libname="Xcursor") )
		self.addStep( TestIfStaticLinked(libname="libstdc", name="stdc++") )
		self.addStep( TestIfStaticLinked(libname="libgcc") )
		self.addStep( TestIfStaticLinked(libname="libgomp", name="openmp") )
		self.addStep( TestIfStaticLinked(libname="libc", name="glibc") )
		self.addStep( TestIfStaticLinked(libname="libm", name="math") )
		self.addStep( TestIfStaticLinked(libname="libpthread", name="pthread") )
		self.addStep( ShowSharedLinkedLibraries() )
		self.addStep( ShowSharedLinkedLibrariesUnitsync() )
		self.addStep( CreateLinuxStaticBundle() )
		self.addStep( HashStuff() )
		self.addStep( RsyncStuff() )
		self.addStep( LocalPostScript() )

class MacOSXQuickBuildFactory(BuildFactory):
	def __init__(self):
		BuildFactory.__init__(self)
		self.workdir = workdir_per_branch
		self.useProgress = False
		self.addStep( Git(repourl=master_repo) )
		self.addStep( GitRenameLocalBranch1() )
		self.addStep( GitRenameLocalBranch2() )
		self.addStep( SyncSubmodules() )
		self.addStep( InitSubmodules() )
		self.addStep( CreateBuildDirPy() )
		self.addStep( BuildConfigNinja() )

class CppCheckBuildFactory(BuildFactory):
	def __init__(self):
		BuildFactory.__init__(self)
		self.addStep( Git(repourl=master_repo) )
		self.addStep( SyncSubmodules() )
		self.addStep( InitSubmodules() )
		self.addStep( CppCheck() )

class DoxygenBuildFactory(BuildFactory):
	def __init__(self):
		BuildFactory.__init__(self)
		self.addStep( Git(repourl=master_repo) )
		self.addStep( SyncSubmodules() )
		self.addStep( InitSubmodules() )
		self.addStep( CreateBuildDirPy() )
		self.addStep( GenerateSources() )
		self.addStep( BuildDocs() )
		self.addStep( RsyncStuff() )

class SourceFactory(BuildFactory):
	def __init__(self):
		BuildFactory.__init__(self)
		self.addStep( Git(repourl=master_repo) )
		self.addStep( SyncSubmodules() )
		self.addStep( InitSubmodules() )
		self.addStep( CreateSourceBundle() )
		self.addStep( HashStuff() )
		self.addStep( RsyncStuff() )

class WikiFactory(BuildFactory):
	def __init__(self):
		BuildFactory.__init__(self)
		self.addStep( Git(repourl=master_repo) )
		self.addStep( GitRenameLocalBranch1() )
		self.addStep( GitRenameLocalBranch2() )
		self.addStep( SyncSubmodules() )
		self.addStep( InitSubmodules() )
		self.addStep( CreateBuildDirPy() )
		self.addStep( BuildConfigNinjaWiki() )
		self.addStep( HTMLManpages() )
		self.addStep( WikiChangelog() )
		self.addStep( WikiSpringSettings() )
		self.addStep( WikiWeaponDefs() )

class ValidationBuildFactory(BuildFactory):
	def addTest(self, gamep, mapp, aip, versionp):
		self.addStep( ValidationTestPrepare(game=gamep, map=mapp, ai=aip, version=versionp ))
		self.addStep( ValidationTestRun(game=gamep, map=mapp, ai=aip, version=versionp ))
		self.addStep( ValidationTestAnalyze(game=gamep, map=mapp, ai=aip, version=versionp ))

	def __init__(self):
		BuildFactory.__init__(self)
		self.useProgress = False
		self.addStep( Git(repourl=master_repo) )
		self.addStep( GitRenameLocalBranch1() )
		self.addStep( GitRenameLocalBranch2() )
		self.addStep( SyncSubmodules() )
		self.addStep( InitSubmodules() )
		self.addStep( CreateBuildDirPy() )
		self.addStep( ValidationTestCleanup() )
		self.addStep( ValidationTestInstall() )
		self.addTest("devgame:test", "Altair_Crossing-V1", "NullAI", "0.1")
		self.addTest("ba:test", "Altair_Crossing-V1", "AAI", "0.9")
		self.addTest("ba:test", "Altair_Crossing-V1", "E323AI", "3.25.0")
		self.addTest("ba:test", "Altair_Crossing-V1", "KAIK", "0.13")
		self.addTest("ba:test", "Altair_Crossing-V1", "RAI", "0.601")
		self.addTest("zk:stable", "Altair_Crossing-V1", "CAI", "")
		self.addTest("swiw:test", "Altair_Crossing-V1", "C.R.A.I.G.", "")
		# BAR seems quiet "unstable" atm
		#self.addTest("bar:test", "Altair_Crossing-V1", "Shard", "dev")
		self.addStep( TestConfig() )
		self.addStep( RsyncStuff() )

class MingwLibsBuildFactory(BuildFactory):
	def __init__(self):
		BuildFactory.__init__(self)
		self.useProgress = False
		self.addStep( Git(repourl=mingwlibs_repo) )
		self.addStep( BuildMingwBoost() )

class MsvcFullBuildFactory(BuildFactory):
	def __init__(self):
		BuildFactory.__init__(self)
		self.workdir = workdir_per_branch
		self.useProgress = False
		self.addStep( Git(repourl=master_repo) )
		self.addStep( GitRenameLocalBranch1() )
		self.addStep( GitRenameLocalBranch2() )
		self.addStep( SyncSubmodules() )
		self.addStep( InitSubmodules() )
		self.addStep( UpdateMsvcLibs() )
		self.addStep( CreateBuildDirPy() )
		self.addStep( BuildConfigNinja() )
		self.addStep( TestConfig() )
		self.addStep( CreateInstaller() )
		#self.addStep( RsyncStuff() )

windows_builder_test = {
	'name': 'full-windows-test',
	'slavenames': ['buildslave-win32'],
	'builddir': 'full-windows-test',
	'factory': WindowsFullBuildFactory(),
	'env': {
		'MINGW_HOST': 'i686-w64-mingw32.static.posix-',
		'CHOST' : 'i686-w64-mingw32.static.posix',
		'ROOT' : '/home/buildbot/mxe/usr',
		'OUTPUTDIR' : 'win32',
		'CMAKEBIN': '/home/buildbot/mxe/usr/bin/i686-w64-mingw32.static.posix-cmake',
		'CMAKEPARAM' :
				' -DMINGWLIBS:PATH=/home/buildbot/mingwlibs'
				' -DCMAKE_SYSTEM_NAME:STRING=Windows'
				' -DUSERDOCS_PLAIN:BOOL=ON'
				' -DCMAKE_INSTALL_PREFIX:PATH='
				' -G Ninja',
		'CXX' : '/home/buildbot/mxe/usr/bin/i686-w64-mingw32.static.posix-g++',
		'CC' : '/home/buildbot/mxe/usr/bin/i686-w64-mingw32.static.posix-gcc',
		'MAKE' : 'ninja',
		'MINGWLIBS_PATH' : '/home/buildbot/mingwlibs',
		'MINGWLIBS_REPO_URL' : 'git://github.com/spring/mingwlibs.git',
		'PATH' : '/home/buildbot/mxe/usr/bin:/usr/bin:/bin',
	}
}

windows_builder_x64 = {
	'name': 'full-windows-x64',
	'slavenames': ['turboss'],
	'builddir': 'full-windows-x64',
	'factory': WindowsFullBuildFactory(),
	'env': {
		'MINGW_HOST': 'x86_64-w64-mingw32.static.posix-',
		'CHOST' : 'x86_64-w64-mingw32.static.posix',
		'ROOT' : '/home/jtoledano/mxe/usr/x86_64-w64-mingw32.static.posix',
		'OUTPUTDIR' : 'win64',
		'CMAKEPARAM' :
				' -DMINGWLIBS:PATH=/home/jtoledano/mingwlibs64'
				' -DCMAKE_FIND_ROOT_PATH:PATH=/home/jtoledano/mxe/usr/libexec/gcc/x86_64-w64-mingw32.static.posix/5.5.0'
				' -DCMAKE_SYSTEM_NAME:STRING=Windows'
				' -DUSERDOCS_PLAIN:BOOL=ON'
				' -DCMAKE_INSTALL_PREFIX:PATH='
				' -G Ninja',
		'CXX' : 'x86_64-w64-mingw32.static.posix-g++',
		'CC' : 'x86_64-w64-mingw32.static.posix-gcc',
		'MAKE' : 'ninja',
		'MINGWLIBS_PATH' : '/home/jtoledano/mingwlibs64',
		'MINGWLIBS_REPO_URL' : 'git://github.com/spring/mingwlibs64.git',
		'PATH' : '/home/jtoledano/mxe/usr/bin:/usr/bin:/bin',
	}
}

macosx_builder = {
	'name': 'full-macosx',
	'slavenames': ['turboss1'],
	'builddir': 'full-macosx',
	'factory': MacOSXFullBuildFactory(),
	'env': {
		'OUTPUTDIR' : 'osx64',
		'MAKE' : 'ninja',
		'CMAKEPARAM':
				' -C../../buildbot/slave/osx/macos_sierra_x64.cmake'
				' -DUSERDOCS_PLAIN:BOOL=ON'
				' -G Ninja',
		'PATH': '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin'
	}
}

lxeparams = "-DPREFER_STATIC_LIBS:BOOL=1 \
-DCMAKE_USE_RELATIVE_PATHS:BOOL=1 \
-DCMAKE_INSTALL_PREFIX:PATH= \
-DBINDIR:PATH=./ \
-DLIBDIR:PATH=./ \
-DDATADIR:PATH=./ \
-DMANDIR:PATH=share/man \
-DDOCDIR:PATH=share/doc/spring \
-DIL_IL_HEADER:PATH=${INCLUDEDIR}/IL/il.h -DIL_INCLUDE_DIR:PATH=${INCLUDEDIR} -DIL_IL_LIBRARY:PATH=${LIBDIR}/libIL.a \
-DIL_LIBRARIES:PATH=${LIBDIR}/libIL.a \
-DILU_LIBRARIES:PATH=${LIBDIR}/libILU.a \
-DPNG_PNG_INCLUDE_DIR:PATH=${INCLUDEDIR} -DPNG_LIBRARY_RELEASE:PATH=${LIBDIR}/libpng.a \
-DJPEG_INCLUDE_DIR:PATH=${INCLUDEDIR} -DJPEG_LIBRARY:PATH=${LIBDIR}/libjpeg.a \
-DTIFF_INCLUDE_DIR:PATH=${INCLUDEDIR} -DTIFF_LIBRARY_RELEASE:PATH=${LIBDIR}/libtiff.a \
-DZLIB_INCLUDE_DIR:PATH=${INCLUDEDIR} -DZLIB_LIBRARY_RELEASE:PATH=${LIBDIR}/libz.a \
-DBZIP2_INCLUDE_DIR:PATH=${INCLUDEDIR} -DBZIP2_LIBRARIES:PATH=${LIBDIR}/libz.a \
-DGLEW_INCLUDE_DIR:PATH=${INCLUDEDIR} -DGLEW_LIBRARIES:PATH=${LIBDIR}/libGLEW.a \
-DLIBUNWIND_INCLUDE_DIRS:PATH=${INCLUDEDIR} -DLIBUNWIND_LIBRARY:PATH=${LIBDIR}/libunwind.a \
-DCURL_INCLUDE_DIR:PATH=${INCLUDEDIR} -DCURL_LIBRARY:PATH=${LIBDIR}/libcurl.a \
-DOPENSSL_INCLUDE_DIR:PATH=${INCLUDEDIR} -DOPENSSL_SSL_LIBRARY:PATH=${LIBDIR}/libssl.a -DOPENSSL_CRYPTO_LIBRARY:PATH=${LIBDIR}/libcrypto.a \
-G Ninja \
".replace("${INCLUDEDIR}", "/home/buildbot/lib/include").replace("${LIBDIR}", "/home/buildbot/lib/lib")

linux_static_builder_x64 = {
	'name': 'linux-static-x64',
	'slavenames': ['buildslave-x64'],
	'builddir': 'linux-static-x64',
	'factory': LinuxStaticBuildFactory(),
	'env': {
		'OUTPUTDIR' : 'linux64',
		'MAKE' : 'ninja',
		'CMAKEPARAM': lxeparams,
	}
}

linux_static_builder_x32 = {
	'name': 'linux-static-x32',
	'slavenames': ['buildslave-i686'],
	'builddir': 'linux-static-x32',
	'factory': LinuxStaticBuildFactory(),
	'env': {
		'OUTPUTDIR' : 'linux32',
		'MAKE' : 'ninja',
		'CMAKEPARAM': lxeparams,
	}
}

macosx_quick_builder = {
	'name': 'quick-macosx',
	'slavenames': ['turboss1'],
	'builddir': 'quick-macosx',
	'factory': MacOSXQuickBuildFactory(),
	'properties': {'default-config': 'fast'},
	'env': macosx_builder['env'],
}

cppcheck_builder = {
	'name': 'cppcheck',
	'slavenames': ['zydox1'],
	'builddir': 'cppcheck',
	'slavebuilddir': 'full-linux',
	'factory': CppCheckBuildFactory()
}

source_builder = {
	'name': 'sourcebuilder',
	'slavenames': ['abma2'],
	'builddir': 'source',
	'factory' : SourceFactory()
}

wiki_builder = {
	'name': 'wikibuilder',
	'slavenames': ['jk1'],
	'builddir': 'wiki',
	'factory' : WikiFactory(),
	'properties': {'default-config': 'fast'},
	'env': {
		'CMAKEPARAM':
				' -DAI_TYPES:STRING=NONE'
				' -DBUILD_spring-legacy:BOOL=OFF'
				' -DBUILD_spring-dedicated:BOOL=OFF'
				' -G Ninja',
		'MAKE' : 'ninja',
	}
}

doxygen_builder = {
	'name': 'doxygen',
	'slavenames': ['abma2'],
	'builddir': 'doxygen',
	'factory': DoxygenBuildFactory(),
	'env' : {
		'MAKE': 'ninja',
		'CMAKEPARAM':
				' -G Ninja'
				' -DCMAKE_FIND_ROOT_PATH:PATH=/opt/oracle-jdk-bin-1.7.0.13'
	}
}

validation_builder = {
	'name': 'validationtests',
	'slavenames': ['zydox1', 'abma1', 'validation'],
	'builddir': 'zydox-fedora',
	'factory': ValidationBuildFactory(),
	'properties': {'default-config': 'validation'},
	'env': {
		'CFLAGS' : '-fsanitize=address -fno-omit-frame-pointer',
		'CXXFLAGS': '-fsanitize=address -fno-omit-frame-pointer',
		'CMAKEPARAM':
				' -G Ninja',
		'MAKE' : 'ninja',
		'ASAN_OPTIONS' : 'detect_leaks=0', # see ASAN_OPTIONS=help=1
	}
}

mingwlibs_builder = {
	'name': 'mingwlibs',
	'slavenames': ['jk1', 'abma2'],
	'builddir': 'mingwlibs',
	'factory': MingwLibsBuildFactory(),
	'properties': {'branch': 'master'}
}

msvc_builder = {
	'name': 'msvc',
	'slavenames': ['supermario'],
	'builddir': 'msvc',
	'factory': MsvcFullBuildFactory(),
	'properties': {'branch': 'master'},
	'env': {
		'MAKE' : 'ninja',
		'CMAKEPARAM': '-DFREETYPE_INCLUDE_DIRS=vclibs/include/freetype'
			' -G Ninja '
			' -DAI_TYPES:STRING=NONE', #FIXME: fix AIs / remove this
		'CXX' : 'cl.exe',
		'CC' : 'cl.exe',
	}
}

#order of these lines are the same as on waterfall
c['builders'].append(windows_builder_test)
c['builders'].append(windows_builder_x64)
c['builders'].append(linux_static_builder_x32)
c['builders'].append(linux_static_builder_x64)
c['builders'].append(macosx_quick_builder)
c['builders'].append(validation_builder)
c['builders'].append(macosx_builder)
c['builders'].append(cppcheck_builder)
c['builders'].append(doxygen_builder)
c['builders'].append(source_builder)
c['builders'].append(wiki_builder)
c['builders'].append(mingwlibs_builder)
c['builders'].append(msvc_builder)


####### STATUS TARGETS

from buildbot.status.html import WebStatus
from buildbot.status.web.authz import Authz
from buildbot.status.web.auth import HTPasswdAuth
authz = Authz(
	auth = HTPasswdAuth('htpasswd'),
	forceBuild = 'auth',
	forceAllBuilds = 'auth',
	stopBuild = 'auth',
	stopAllBuilds = 'auth',
	stopChange = 'auth',
	cancelPendingBuild = 'auth'
)
web = WebStatus(
	http_port='tcp:7778:interface=127.0.0.1',
	authz=authz,
	change_hook_dialects={ 'github' : {} }
)
c['status'].append(web)

from buildbot.status import words
irc = words.IRC("irc.springrts.com", "MrBuild",
	channels=["sy"],
	password=passwords.mrbuild,
	notify_events={
		'successToFailure': 1,
		'warningsToFailure': 1,
		'failureToSuccess': 1,
		'failureToWarnings': 1,
	})
c['status'].append(irc)

####### DEBUGGING OPTIONS

#c['debugPassword'] = "debugpassword"
#c['manhole'] = buildbot.manhole.PasswordManhole("tcp:9999:interface=127.0.0.1", "admin", "password")

####### PROJECT IDENTITY

c['projectName'] = "Spring"
c['projectURL'] = "https://springrts.com"
c['buildbotURL'] = "http://buildbot.springrts.com/"
